package com.sec.android.app.myfiles.feature.mousekeyboard;

import android.content.Context;
import android.view.MotionEvent;
import android.widget.AbsListView;

import com.sec.android.app.myfiles.facade.MyFilesFacade;
import com.sec.android.app.myfiles.facade.cmd.CopyMoveCmd;
import com.sec.android.app.myfiles.facade.cmd.DeleteRecordCmd;
import com.sec.android.app.myfiles.facade.cmd.ToSelectModeCmd;
import com.sec.android.app.myfiles.fragment.AbsMyFilesFragment;
import com.sec.android.app.myfiles.fragment.filelist.OnItemChangedListener;
import com.sec.android.app.myfiles.info.AppConstants;
import com.sec.android.app.myfiles.log.Log;
import com.sec.android.app.myfiles.module.abstraction.FileRecord;
import com.sec.android.app.myfiles.operation.FileOperator;
import com.sec.android.app.myfiles.util.PreferenceUtils;
import com.sec.android.app.myfiles.util.UiUtils;
import com.sec.android.app.myfiles.widget.listview.pinchview.PinchGridView;

import java.util.ArrayList;

public class MouseKeyboardImp {
    private boolean mIsCtrlCopied = false;
    private boolean mIsCtrlMoved = false;
    private boolean mIsShiftPressed = false;
    private boolean mIsCtrlPressed = false;
    private int mStartPosition;
    private ArrayList<FileRecord> mSelectedRecordList;
    private ArrayList<OnItemChangedListener> mOnItemChangedListener = null;

    private static final int LIST_DEPTH = PinchGridView.MAX_PINCH_DEPTH + 1;

    public MouseKeyboardImp() {
    }

    public boolean isCtrlCopied() {
        return mIsCtrlCopied;
    }

    public void setCtrlCopy(boolean ctrlCopy) {
        mIsCtrlCopied = ctrlCopy;
    }

    public boolean isCtrlMoved() {
        return mIsCtrlMoved;
    }

    public void setCtrlMove(boolean isMoved) {
        mIsCtrlMoved = isMoved;
    }

    private void setSelectedFile(ArrayList<FileRecord> srcRecordList) {
        mSelectedRecordList = srcRecordList;
    }

    public ArrayList<FileRecord> getSelectedFile() {
        return mSelectedRecordList;
    }

    public boolean isShiftPressed() {
        return mIsShiftPressed;
    }

    public boolean isCtrlPressed() {
        return mIsCtrlPressed;
    }

    public void setCtrlPress(boolean ctrlPress) {
        mIsCtrlPressed = ctrlPress;
    }

    public void setShiftPress(boolean shiftPress) {
        mIsShiftPressed = shiftPress;
    }

    public void setFocusedListIndex(int startPos) {
        mStartPosition = startPos > -1 ? startPos : 0;
    }

    private int getFocusedListIndex() {
        return mStartPosition;
    }

    public void onCtrlC(AbsMyFilesFragment fragment, FileRecord record) {
        boolean selectionMode = false;
        FileRecord.StorageType storageType = record.getStorageType();
        if (!FileRecord.StorageType.FolderTree.equals(storageType)) {
            if (fragment.isSelectActionMode()) {
                ArrayList<FileRecord> srcRecordList = fragment.getSelectedFile();
                if (srcRecordList != null && !srcRecordList.isEmpty()) {
                    setSelectedFile(srcRecordList);
                    setCtrlCopy(true);
                    fragment.finishActionMode();
                }
                selectionMode = true;
            }
        }
        // FolderTree & Local
        if (!selectionMode &&
                (FileRecord.StorageType.Cloud.equals(storageType) ||
                        FileRecord.StorageType.FolderTree.equals(storageType) ||
                        FileRecord.StorageType.Local.equals(storageType))) {
            ArrayList<FileRecord> srcRecordList = new ArrayList<>();
            srcRecordList.add(record);
            if (!srcRecordList.isEmpty()) {
                setSelectedFile(srcRecordList);
                setCtrlCopy(true);
            }
        }
    }

    public void onCtrlX(AbsMyFilesFragment fragment, FileRecord record) {
        boolean selectionMode = false;
        if (record.getStorageType() != FileRecord.StorageType.FolderTree) {
            if (fragment.isSelectActionMode()) {
                ArrayList<FileRecord> srcRecordList = fragment.getSelectedFile();
                if (srcRecordList != null && !srcRecordList.isEmpty()) {
                    setSelectedFile(srcRecordList);
                    setCtrlMove(true);
                    fragment.finishActionMode();
                }
                selectionMode = true;
            }
        }
        // FolderTree & Local
        if (!selectionMode) {
            ArrayList<FileRecord> srcRecordList = new ArrayList<>();
            srcRecordList.add(record);
            if (!srcRecordList.isEmpty()) {
                setSelectedFile(srcRecordList);
                setCtrlMove(true);
            }
        }
    }

    public void onCtrlV(AbsMyFilesFragment fragment, FileRecord curRecord) {
        Context context = fragment.getContext();
        if (context != null) {
            context = context.getApplicationContext();

            FileOperator.Operation operationType = null;
            if (isCtrlCopied()) {
                operationType = FileOperator.Operation.COPY;
            } else if (isCtrlMoved()) {
                operationType = FileOperator.Operation.MOVE;
            }

            if (operationType != null && curRecord != null) {
                ArrayList<FileRecord> srcRecordList = getSelectedFile();
                if (srcRecordList != null) {
                    if (!srcRecordList.isEmpty()) {
                        MyFilesFacade.copymoveRecord(fragment.getProcessId(), context, operationType,
                                CopyMoveCmd.OperationProgress.DO_OPERATE, fragment, srcRecordList, curRecord);
                    }
                }
            }
        } else {
            Log.e(this, "getContext[Activity] is null");
        }
    }

    public void onCtrlA(AbsMyFilesFragment fragment) {
        if (!fragment.isSelectActionMode() && fragment.getListItemCount() > 0) {
            MyFilesFacade.toSelectMode(fragment.getProcessId(), fragment, ToSelectModeCmd.SelectModeType.SELECT_MODE);
        }
        fragment.selectAll(true);
    }

    public void onF2(AbsMyFilesFragment fragment, AbsListView listViewImp, FileRecord record, int position) {
        Context context = fragment.getContext();
        if (context != null) {
            context = context.getApplicationContext();
            if (!fragment.isSelectActionMode()) {
                if (listViewImp != null) {
                    MyFilesFacade.toSelectMode(fragment.getProcessId(), fragment, ToSelectModeCmd.SelectModeType.SELECT_MODE);
                    listViewImp.setItemChecked(position, true);
                }
            }
            record.setStorageType(FileRecord.StorageType.Local);
            ArrayList<FileRecord> srcRecordList = new ArrayList<>();
            srcRecordList.add(record);
            MyFilesFacade.renameRecord(fragment.getProcessId(), context, fragment, srcRecordList);
        } else {
            Log.e(this, "getContext[Activity] is null");
        }
    }

    public void onDel(AbsMyFilesFragment fragment, AbsListView listViewImp) {
        Context context = fragment.getContext();
        if (context != null) {
            context = context.getApplicationContext();
            if (fragment.isSelectActionMode()) {
                if (listViewImp != null) {
                    MyFilesFacade.deleteRecord(fragment.getProcessId(), context, fragment, fragment.getSelectedFile(), DeleteRecordCmd.OperationProgress.SHOW_CONFIRM_POPUP);
                }
            }
        } else {
            Log.e(this, "onDel() - getContext[Activity] is null");
        }
    }

    public void onCtrlD(AbsMyFilesFragment fragment, FileRecord record, AbsListView listViewImp, int position) {
        Context context = fragment.getContext();
        if (context != null) {
            context = context.getApplicationContext();
            boolean isOneItem = false;
            if (record.getStorageType() != FileRecord.StorageType.FolderTree) {
                if (!fragment.isSelectActionMode()) {
                    if (listViewImp != null) {
                        MyFilesFacade.toSelectMode(fragment.getProcessId(), fragment, ToSelectModeCmd.SelectModeType.SELECT_MODE);
                        listViewImp.setItemChecked(position, true);
                        fragment.updateActionBarMenu();
                        isOneItem = true;
                    }
                } else {
                    ArrayList<FileRecord> srcRecordList = fragment.getSelectedFile();
                    if (!srcRecordList.isEmpty()) {
                        MyFilesFacade.deleteRecord(fragment.getProcessId(), context, fragment, srcRecordList, DeleteRecordCmd.OperationProgress.SHOW_CONFIRM_POPUP);
                    }
                }
            } else {
                isOneItem = true;
            }

            if (isOneItem) {
                ArrayList<FileRecord> srcRecordList = new ArrayList<>();
                srcRecordList.add(record);
                MyFilesFacade.deleteRecord(fragment.getProcessId(), context, fragment, srcRecordList, DeleteRecordCmd.OperationProgress.SHOW_FOLDER_TREE_CONFIRM_POPUP);
            }
        } else {
            Log.e(this, "getContext[Activity] is null");
        }
    }

    public void onShiftArrowUp(AbsMyFilesFragment fragment, AbsListView listViewImp, int position) {
        if (listViewImp != null) {
            if (!fragment.isSelectActionMode()) {
                MyFilesFacade.toSelectMode(fragment.getProcessId(), fragment, ToSelectModeCmd.SelectModeType.SELECT_MODE);
                listViewImp.setItemChecked(position, true);
            }
            if ((position - 1) >= 0) {
                listViewImp.setItemChecked(position - 1, true);
            }
            fragment.updateActionBarMenu();
        }
    }

    public void onShiftArrowDown(AbsMyFilesFragment fragment, AbsListView listViewImp, int position) {
        if (listViewImp != null) {
            if (!fragment.isSelectActionMode()) {
                MyFilesFacade.toSelectMode(fragment.getProcessId(), fragment, ToSelectModeCmd.SelectModeType.SELECT_MODE);
                listViewImp.setItemChecked(position, true);
            }
            if ((position + 1) >= 0) {
                listViewImp.setItemChecked(position + 1, true);
            }
            fragment.updateActionBarMenu();
        }
    }

    public void onShiftMouseClick(AbsMyFilesFragment fragment, AbsListView listViewImp, int lastPostion) {
        Log.e(this, "shiftMouseClick - lastPosition " + lastPostion);
        int start = getFocusedListIndex();
        if (listViewImp != null) {
            if (!fragment.isSelectActionMode()) {
                MyFilesFacade.toSelectMode(fragment.getProcessId(), fragment, ToSelectModeCmd.SelectModeType.SELECT_MODE);
            }
            if (lastPostion != start && lastPostion > -1) {
                if (lastPostion > start) {
                    for (int i = start; i <= lastPostion; i++) {
                        listViewImp.setItemChecked(i, true);
                    }
                } else {
                    for (int i = start; i >= lastPostion; i--) {
                        listViewImp.setItemChecked(i, true);
                    }
                }
            }
            fragment.updateActionBarMenu();
        }
    }

    public void onCtrlMouseClick(AbsMyFilesFragment fragment, AbsListView listViewImp, int position) {
        if (listViewImp != null) {
            if (!fragment.isSelectActionMode()) {
                MyFilesFacade.toSelectMode(fragment.getProcessId(), fragment, ToSelectModeCmd.SelectModeType.SELECT_MODE);
            }
            if (position > -1) {
                listViewImp.setItemChecked(position, true);
                fragment.updateActionBarMenu();
            }
        }
    }

    public void onCtrlMouseWheel(MotionEvent event, AbsMyFilesFragment fragment, FileRecord record) {
        Context context = fragment.getContext();
        if (context == null) {
            return;
        }

        int depth = LIST_DEPTH;

        int listType = PreferenceUtils.getViewAs(context, PreferenceUtils.getViewAsKey(record));

        if (listType == AppConstants.ViewType.GRID) {
            depth = PreferenceUtils.getGridViewPinchDepth(context);
        }

        if (event.getAxisValue(MotionEvent.AXIS_VSCROLL) < 0.0f) {
            onScrollDown(depth, context, fragment, record);
        } else {
            onScrollUp(depth, context, fragment, record);
        }
    }

    private void onScrollDown(int depth, Context context, AbsMyFilesFragment fragment, FileRecord record) {
        boolean depthChanged = false;
        boolean viewChanged = false;

        if (depth < LIST_DEPTH) {
            depth = getIncDepth(depth, record);
            depthChanged = true;
            if (depth >= LIST_DEPTH) {
                viewChanged = true;
            }
        }
        if (depthChanged) {
            changeView(depth, viewChanged, context, fragment.getListView(), record);
        }
    }

    private int getIncDepth(int depth, FileRecord record) {
        int ret = depth + 1;
        if (UiUtils.isCategoryFolderList(record)) {
            if (ret == PinchGridView.MAX_PINCH_DEPTH) {
                ret++;
            }
        }
        return ret;
    }

    private void onScrollUp(int depth, Context context, AbsMyFilesFragment fragment, FileRecord record) {
        boolean depthChanged = false;
        boolean viewChanged = false;

        if (depth > 0) {
            depth = getDecDepth(depth, record);
            depthChanged = true;
            if (depth <= PinchGridView.MAX_PINCH_DEPTH) {
                viewChanged = true;
            }
        }

        if (depthChanged) {
            changeView(depth, viewChanged, context, fragment.getListView(), record);
        }
    }

    private int getDecDepth(int depth, FileRecord record) {
        int ret = depth - 1;
        if (UiUtils.isCategoryFolderList(record)) {
            if (ret == PinchGridView.MAX_PINCH_DEPTH) {
                ret--;
            }
        }
        return ret;
    }

    private void changeView(int depth, boolean viewChanged, Context context, AbsListView listView, FileRecord record) {
        PreferenceUtils.ViewAsKey viewAsKey = PreferenceUtils.getViewAsKey(record);
        if (depth == LIST_DEPTH) {
            PreferenceUtils.setViewAs(context, AppConstants.ViewType.LIST_DETAIL, viewAsKey);
            UiUtils.refreshLocalBroadcastIntent(context, AppConstants.MYFILES_ACTION_VIEW_AS_CHANGED);
        } else {
            PreferenceUtils.setGridViewPinchDepth(context, depth);

            if (viewChanged) {
                PreferenceUtils.setViewAs(context, AppConstants.ViewType.GRID, viewAsKey);
                UiUtils.refreshLocalBroadcastIntent(context, AppConstants.MYFILES_ACTION_VIEW_AS_CHANGED);
            } else {
                if (listView instanceof PinchGridView) {
                    ((PinchGridView) listView).setPinchDepth(depth);
                }
            }
        }
    }

    public void onEnter(AbsMyFilesFragment fragment, FileRecord record) {
        MyFilesFacade.executeRecord(fragment.getProcessId(), fragment.getFileListActivity(), record);
    }

    public void addOnItemChangedListener(OnItemChangedListener listener) {
        if (mOnItemChangedListener == null) {
            mOnItemChangedListener = new ArrayList<>();
        }
        mOnItemChangedListener.add(listener);
    }

    public void removeOnItemChangedListener(OnItemChangedListener listener) {
        if (mOnItemChangedListener != null) {
            mOnItemChangedListener.remove(listener);
        }
    }

    public void notifyItemUpdated() {
        if (mOnItemChangedListener != null) {
            for (OnItemChangedListener listener : mOnItemChangedListener) {
                if (listener != null) {
                    listener.onItemUpdated();
                }
            }
        }
    }
}
